package br.eng.eliseu.gwt.gestaoWeb.client.ui.core;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import br.eng.eliseu.gwt.gestaoWeb.client.service.EnderecoService;
import br.eng.eliseu.gwt.gestaoWeb.client.service.EnderecoServiceAsync;
import br.eng.eliseu.gwt.gestaoWeb.client.ui.component.textBox.MaskedTextBox;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.Cidade;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.Estado;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.Pais;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.TipoLogradouro;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.text.shared.Renderer;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ValueListBox;
import com.google.gwt.user.client.ui.Widget;

public class EnderecoView extends Composite {

	private static EnderecoViewUiBinder uiBinder = GWT.create(EnderecoViewUiBinder.class);
	interface EnderecoViewUiBinder extends UiBinder<Widget, EnderecoView> {	}
	
	@UiField MaskedTextBox cepTBox;
	@UiField (provided = true) ValueListBox<Pais> paisLBox;
	@UiField (provided = true) ValueListBox<Estado> estadoLBox;
//	@UiField TextBox estadoTBox;
	@UiField (provided = true) ValueListBox<Cidade> cidadeLBox;
//	@UiField TextBox cidadeTBox;
	@UiField (provided = true) ValueListBox<TipoLogradouro> tipoLogradouroLBox;
	@UiField SuggestBox logradouroSBox;
	@UiField TextBox numeroTBox;
	@UiField TextBox complementoTBox;
	@UiField SuggestBox bairroSBox;

	private List<Pais> paisList = new ArrayList<Pais>();
	private List<Estado> estadoList = new ArrayList<Estado>();
	private List<Cidade> cidadeList = new ArrayList<Cidade>();
	private List<TipoLogradouro> tipoLogradouroList = new ArrayList<TipoLogradouro>();

	private EnderecoServiceAsync enderecoService = GWT.create(EnderecoService.class);

	private Comparator<Pais> comparatorPais = new Comparator<Pais>() {
		public int compare(Pais a, Pais b) {return a.compareTo(b);}};
	private Comparator<Estado> comparatorEstado = new Comparator<Estado>() {
		public int compare(Estado a, Estado b) {return a.compareTo(b);}};
	private Comparator<Cidade> comparatorCidade = new Comparator<Cidade>() {
		public int compare(Cidade a, Cidade b) {return a.compareTo(b);}};
	private Comparator<TipoLogradouro> comparatorTipoLogradouro = new Comparator<TipoLogradouro>() {
		public int compare(TipoLogradouro a, TipoLogradouro b) {return a.compareTo(b);}};

		
	public EnderecoView() {
		paisLBox = new ValueListBox<Pais>( new Renderer<Pais>() {
			public String render(Pais p) {
				String s = "";
				if (p != null) {
			        s = p.getNome();
			    }
			    return s;
			}
			public void render(Pais p, Appendable appendable) throws IOException {
				String s = render(p);
		        appendable.append(s);				
			}
		});
		estadoLBox = new ValueListBox<Estado>( new Renderer<Estado>() {
			public String render(Estado e) {
				String s = "";
				if (e != null) {
			        s = e.getSigla();
			    }
			    return s;
			}
			public void render(Estado e, Appendable appendable) throws IOException {
				String s = render(e);
		        appendable.append(s);				
			}
		});
		cidadeLBox = new ValueListBox<Cidade>( new Renderer<Cidade>() {
			public String render(Cidade c) {
				String s = "";
				if (c != null) {
			        s = c.getNome();
			    }
			    return s;
			}
			public void render(Cidade c, Appendable appendable) throws IOException {
				String s = render(c);
		        appendable.append(s);				
			}
		});
		tipoLogradouroLBox = new ValueListBox<TipoLogradouro>( new Renderer<TipoLogradouro>() {
			public String render(TipoLogradouro tl) {
				String s = "";
				if (tl != null) {
			        s = tl.getNome();
			    }
			    return s;
			}
			public void render(TipoLogradouro tl, Appendable appendable) throws IOException {
				String s = render(tl);
		        appendable.append(s);				
			}
		});
		
		
		initWidget(uiBinder.createAndBindUi(this));

		cepTBox.setMask("99.999-999");
		
		buscaListaPaisAsync();
		buscaListaTipoLogradouroAsync();

		bind();

	}

	public void bind() {
		// --- Evendo de mudanca de estado do comboPais
	    getPaisLBox().addValueChangeHandler(new ValueChangeHandler<Pais>(){
			public void onValueChange(ValueChangeEvent<Pais> event) {

				estadoLBox.setValue(null);
				cidadeLBox.setValue(null);
			
				Pais p = event.getValue();
				if ("BRASIL".equals(p.getNome())){
					buscaListaEstadoAsync(p);
				}
			}
	    });


		// --- Evendo de mudanca de estado do comboEstado
	    getEstadoLBox().addValueChangeHandler(new ValueChangeHandler<Estado>(){
			public void onValueChange(ValueChangeEvent<Estado> event) {
				Pais p = getPaisLBox().getValue();
				Estado e = event.getValue();
				buscaListaCidadeAsync(p, e);
			}
	    });

}

	
	public void setAll( String cep, Pais pais, Estado estado, Cidade cidade, 
			TipoLogradouro tipoLogradouro, String logradouro, String numero, 
			String complemento, String bairro){

		setCep(cep);
		setPais(pais);
		setEstado(estado);
		setCidade(cidade);
		setTipoLogradouro(tipoLogradouro);
		setLogradouro(logradouro);
		setNumero(numero);
		setComplemento(complemento);
		setBairro(bairro);
		
	}

	
	public String getCep() {
		if (cepTBox!=null && !"".equals(cepTBox.getValue())){
			return cepTBox.getValue();
		} else {
			return "";
		}
	}
	public void setCep(String cep) {
		if (cep==null){
			cep = "";
		}
		this.cepTBox.setValue(cep);
	}

	
	public ValueListBox<Pais> getPaisLBox() {
		return paisLBox;
	}
	public void populaPaisLBox( List<Pais> lista){
		this.paisList = lista;
		Collections.sort(this.paisList, comparatorPais);
		paisLBox.setAcceptableValues(this.paisList);
	}
	public void setPais(String pais) {
		if (pais!=null){
			if ("".equals(pais)){
				paisLBox.setValue(null);
			} else {
				Pais p = new Pais();
				p.setNome(pais);
				int i = Collections.binarySearch(paisList, p, comparatorPais);
				if (i==-1){
					p = null;
				} else {
					p = paisList.get(i);
				}
				paisLBox.setValue(p);
			}
		}
	}
	public void setPais(Pais pais) {
		if (pais!=null){
			paisLBox.setValue(pais);
		}
	}
	public String getPaisItem(){
		if (paisLBox.getValue()!=null){
			return paisLBox.getValue().getNome();
		} else {
			return "";
		}
	}
	public Pais getPais(){
		return paisLBox.getValue();
	}

	
	public ValueListBox<Estado> getEstadoLBox() {
		return estadoLBox;
	}
	public void populaEstadoLBox( List<Estado> lista){
		this.estadoList = lista;
		Collections.sort(this.estadoList, comparatorEstado);
		estadoLBox.setAcceptableValues(this.estadoList);
	}
	public void setEstado(String estado) {
		if (estado!=null){
			if ("".equals(estado)){
				estadoLBox.setValue(null);
			} else {
				Estado e = new Estado();
				e.setNome(estado);
				int i = Collections.binarySearch(estadoList, e, comparatorEstado);
				if (i==-1){
					e = null;
				} else {
					e = estadoList.get(i);
				}
				estadoLBox.setValue(e);
			}
		}
	}
	public void setEstado(Estado estado) {
		if (estado!=null){
			estadoLBox.setValue(estado);
		}
	}
	public String getEstadoItem(){
		if (estadoLBox.getValue()!=null){
			return estadoLBox.getValue().getSigla();
		} else {
			return "";
		}
	}
	public Estado getEstado(){
		return estadoLBox.getValue();
	}

	
	public ValueListBox<Cidade> getCidadeLBox() {
		return cidadeLBox;
	}
	public void populaCidadeTBox( List<Cidade> lista){ 
		this.cidadeList = lista;
		Collections.sort(this.cidadeList, comparatorCidade);
		cidadeLBox.setAcceptableValues(this.cidadeList);
	}
	public void setCidade(String cidade) {
		if (cidade!=null){
			if ("".equals(cidade)){
				cidadeLBox.setValue(null);
			} else {
				Cidade c = new Cidade();
				c.setNome(cidade);
				int i = Collections.binarySearch(cidadeList, c, comparatorCidade);
				if (i==-1){
					c = null;
				} else {
					c = cidadeList.get(i);
				}
				cidadeLBox.setValue(c);
			}
		}
	}
	public void setCidade(Cidade cidade) {
		if (cidade!=null){
			cidadeLBox.setValue(cidade);
		}
	}
	public String getCidadeItem(){
		if (cidadeLBox.getValue()!=null){
			return cidadeLBox.getValue().getNome();
		} else {
			return "";
		}
	}
	public Cidade getCidade(){
		return cidadeLBox.getValue();
	}


	public ValueListBox<TipoLogradouro> getTipoLogradouroLBox() {
		return tipoLogradouroLBox;
	}
	public void populaTipoLogradouroLBox( List<TipoLogradouro> lista){
		this.tipoLogradouroList = lista;
		Collections.sort(this.tipoLogradouroList, comparatorTipoLogradouro);
		tipoLogradouroLBox.setAcceptableValues(this.tipoLogradouroList);
	}
	public void setTipoLogradouro(String tipoLogradouro) {
		if (tipoLogradouro!=null){
			if ("".equals(tipoLogradouro)){
				tipoLogradouroLBox.setValue(null);
			} else {
				TipoLogradouro tl = new TipoLogradouro();
				tl.setNome(tipoLogradouro);
				int i = Collections.binarySearch(tipoLogradouroList, tl, comparatorTipoLogradouro);
				if (i==-1){
					tl = null;
				} else {
					tl = tipoLogradouroList.get(i);
				}
				tipoLogradouroLBox.setValue(tl);
			}
		}
	}
	public void setTipoLogradouro(TipoLogradouro tipoLogradouro) {
		if (tipoLogradouro!=null){
			tipoLogradouroLBox.setValue(tipoLogradouro);
		}
	}
	public String getTipoLogradouroItem(){
		if (tipoLogradouroLBox.getValue()!=null){
			return tipoLogradouroLBox.getValue().getNome();
		} else {
			return "";
		}
	}
	public TipoLogradouro getTipoLogradouro(){
		return tipoLogradouroLBox.getValue();
	}

	
	public String getLogradouro() {
		if (logradouroSBox!=null && !"".equals(logradouroSBox.getValue())){
			return logradouroSBox.getValue();
		} else {
			return "";
		}
	}
	public void setLogradouro(String logradouro) {
		if (logradouro==null){
			logradouro = "";
		}
		this.logradouroSBox.setValue(logradouro);
	}

	public String getNumero() {
		if (numeroTBox!=null && !"".equals(numeroTBox.getValue())){
			return numeroTBox.getValue();
		} else {
			return "";
		}
	}
	public void setNumero(String numero) {
		if (numero==null){
			numero = "";
		}
		this.numeroTBox.setValue(numero);
	}

	public String getComplemento() {
		if (complementoTBox!=null && !"".equals(complementoTBox.getValue())){
			return complementoTBox.getValue();
		} else {
			return "";
		}
	}
	public void setComplemento(String complemento) {
		if (complemento==null){
			complemento = "";
		}
		this.complementoTBox.setValue(complemento);
	}

	public String getBairro() {
		if (bairroSBox!=null && !"".equals(bairroSBox.getValue())){
			return bairroSBox.getValue();
		} else {
			return "";
		}
	}
	public void setBairro(String bairro) {
		if (bairro==null){
			bairro = "";
		}
		this.bairroSBox.setValue(bairro);
	}

	public void limpaEnderecoView(){
		setCep("");
		setPais("BRASIL");
		setEstado("");
		setCidade("");
		setTipoLogradouro("");
		setLogradouro("");
		setNumero("");
		setComplemento("");
		setBairro("");
	}

	private void buscaListaPaisAsync(){
		enderecoService.listaPaises(new AsyncCallback<List<Pais>>() {
			public void onFailure(Throwable arg0) {
			}
			public void onSuccess(List<Pais> paises) {
				populaPaisLBox(paises);
				setPais("BRASIL");
				buscaListaEstadoAsync(getPaisLBox().getValue());
				
			}
		});
	}
	private void buscaListaEstadoAsync(Pais pais){
		enderecoService.listaEstado(pais, new AsyncCallback<List<Estado>>() {
			public void onFailure(Throwable arg0) {
			}
			public void onSuccess(List<Estado> estados) {
				populaEstadoLBox(estados);
			}
		});
	}

	private void buscaListaCidadeAsync(Pais pais, Estado estado){
		enderecoService.listaCidade(pais, estado, new AsyncCallback<List<Cidade>>() {
			public void onFailure(Throwable arg0) {
				System.out.println(arg0.getMessage());
			}
			public void onSuccess(List<Cidade> cidades) {
				populaCidadeTBox(cidades);
			}
		});
	}

	private void buscaListaTipoLogradouroAsync(){
		enderecoService.listaTipoLogradouro(new AsyncCallback<List<TipoLogradouro>>() {
			public void onFailure(Throwable arg0) {
			}
			public void onSuccess(List<TipoLogradouro> tipoLogradouro) {
				populaTipoLogradouroLBox(tipoLogradouro);
			}
		});
	}

}
